<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8"/>
  <title>数据大屏</title>
  <link href="css/style.css" rel="stylesheet"/>

  <script src="../js/axios.min.js"></script>
  <script src="../js/mqtt/mqtt.min.js"></script>
  <!--  <script src="./js/jquery-1.8.0.min.js" type="text/javascript"></script>-->
  <!-- ztree -->
  <link href="./js/ztree/css/zTreeStyle/zTreeStyle.css" rel="stylesheet" type="text/css">

  <script src="./js/ztree/js/jquery-1.4.4.min.js" type="text/javascript"></script>
  <script src="./js/ztree/js/jquery.ztree.core.min.js" type="text/javascript"></script>
  <script src="./js/ztree/js/jquery.ztree.excheck.min.js" type="text/javascript"></script>
  <script src="./js/ztree/js/jquery.ztree.exedit.min.js" type="text/javascript"></script>

  <script src="js/echarts.min.js" type="text/javascript"></script>

  <script src="../js/threejs/libs/draco/draco_encoder.js"></script>

  <link href="../js/threejs/libs/codemirror/codemirror.css" rel="stylesheet"/>
  <link href="../js/threejs/libs/codemirror/theme/monokai.css" rel="stylesheet"/>
  <script src="../js/threejs/libs/codemirror/codemirror.js"></script>
  <script src="../js/threejs/libs/codemirror/mode/javascript.js"></script>
  <script src="../js/threejs/libs/codemirror/mode/glsl.js"></script>

  <script src="../js/threejs/libs/esprima.js"></script>
  <script src="../js/threejs/libs/jsonlint.js"></script>
  <script src="../js/threejs/libs/glslprep.min.js"></script>
  <script src="../js/threejs/libs/signals.min.js"></script>

  <link href="../js/threejs/libs/codemirror/addon/dialog.css" rel="stylesheet"/>
  <link href="../js/threejs/libs/codemirror/addon/show-hint.css" rel="stylesheet"/>
  <link href="../js/threejs/libs/codemirror/addon/tern.css" rel="stylesheet"/>

  <script src="../js/threejs/libs/codemirror/addon/dialog.js"></script>
  <script src="../js/threejs/libs/codemirror/addon/show-hint.js"></script>
  <script src="../js/threejs/libs/codemirror/addon/tern.js"></script>
  <script src="../js/threejs/libs/acorn/acorn.js"></script>
  <script src="../js/threejs/libs/acorn/acorn_loose.js"></script>
  <script src="../js/threejs/libs/acorn/walk.js"></script>
  <script src="../js/threejs/libs/ternjs/polyfill.js"></script>
  <script src="../js/threejs/libs/ternjs/signal.js"></script>
  <script src="../js/threejs/libs/ternjs/tern.js"></script>
  <script src="../js/threejs/libs/ternjs/def.js"></script>
  <script src="../js/threejs/libs/ternjs/comment.js"></script>
  <script src="../js/threejs/libs/ternjs/infer.js"></script>
  <script src="../js/threejs/libs/ternjs/doc_comment.js"></script>
  <script src="../js/threejs/libs/tern-threejs/threejs.js"></script>
</head>

<body>
<script type="module">
  import * as THREE from '../js/threejs/build/three.module.js'

  import Displayer from './js/Displayer.js'
  import Content from './js/Content.js'
  import Header from './js/Header.js'

  import {RemoveObjectCommand} from "../js/threejs/commands/Commands.js";

  window.URL = window.URL || window.webkitURL
  window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder

  Number.prototype.format = function () {
    return this.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')
  }

  // 初始化Display模块
  let displayer = new Displayer()

  window.editor = displayer // Expose displayer to Console
  window.displayer = displayer // Expose displayer to Console
  window.THREE = THREE // Expose THREE to APP Scripts and Console

  // 初始化header
  document.body.appendChild(new Header(displayer).dom)
  document.body.appendChild(new Content(displayer).dom)

  /* 1、初始化浏览器的IndexedDB */
  displayer.storage.init(function () {
    // 2、后台获取场景配置信息
    displayer.storageRemote.getDeployConfig().then((deployConfig) => {
      // 读取浏览器缓存
      displayer.storage.get(function (state) {
        if (state !== undefined) {
          console.log('>>>>>>>>>>>>>> 缓存加载模型 <<<<<<<<<<<<<')
          if (isJSON(state)) {
            displayer.fromJSON(state).then(scene => {
              console.log('缓存加载模型 完成', scene)
              /* 读取场景信息和设备信息，遍历 */
              deployConfigInit(deployConfig)
            })
          }
        } else {
          // 没有缓存时，直接执行模型配置初始化
          console.log('>>>>>>>>>>>>>> 后台加载模型 <<<<<<<<<<<<<')
          deployConfigInit(deployConfig)
        }
        setAmbientLight()
      })
    })

    /**
     * 模型配置初始化
     * @author zhouwr
     */
    let deployConfigInitTimeout
    function deployConfigInit(deployConfig) {
      console.log('>>>>>>>>>> 模型配置初始化 <<<<<<<<<')
      clearTimeout(deployConfigInitTimeout)
      // 拿到场景配置信息中的模型文件，以","分割
      let modelFiles = deployConfig['modelFile'].split(',') // 后台请求的部署配置数据：场景数据
      for (const file of modelFiles) {
        let sceneConfig = JSON.parse(JSON.stringify(deployConfig))
        sceneConfig.modelFile = file
        delete sceneConfig.deviceInstances
        displayer.signals.objectAllConfiged.active = false
        objectQueryCompared('file', file, sceneConfig)
      }
      // 2、比对设备
      let deviceConfs = displayer.deployConfig['deviceInstances']
      if (deviceConfs !== undefined && deviceConfs.length > 0) {
        for (const deviceConf of deviceConfs) {
          displayer.signals.objectAllConfiged.active = false
          objectQueryCompared('uuid', deviceConf.id, deviceConf)
        }
      }
    }

    /**
     * 设备查找并对比
     * @author zhouwenrong
     * @propertyName 查询关键字的名称
     * @propertyValue 查询关键字的值
     * @config 配置信息
     * @TODO 后台把模型的文件修改后，前端请求文件时，要替换掉模型对象
     */
    function objectQueryCompared(propertyName, propertyValue, config) {
      let object = displayer.scene.getObjectByProperty(propertyName, propertyValue)
      displayer.signals.objectAllConfiged.active = false
      if (object) {
        // 找到对象
        console.log('找到对象', propertyName, propertyValue, config.name)
        // 先拿到对象的medel跟配置信息的文件名对比
        if (object.file === config.modelFile) {
          // 模型文件相等，直接配置，无需重新请求模型文件
          displayer.configObj(object, config)
        } else {
          // 不想等
          console.log(`1、模型[${object.name}]的文件[${object.file}]与配置信息文件[${config.modelFile}]不匹配`)
          // 1、先删除模型对象
          console.log(`2、删除对象[${object.name}]`)
          new RemoveObjectCommand(displayer, object)
          // 重新获取对象
          getObject(config)
        }
      } else {
        // 找不到对象，匹配不成功，后台加载模型文件
        console.log('找不到对象', propertyName, propertyValue, config.name)
        getObject(config)
      }
    }

    function getObject(config) {
      /* 查找相同文件的现有对象 */
      const existObj = displayer.scene.getObjectByProperty('file', config.modelFile);
      displayer.signals.objectAllConfiged.active = false
      if(existObj) {
        console.log(`克隆已存在的[${existObj.name}]模型`)
        const clone = existObj.clone();
        displayer.configObj(clone, config)
        displayer.addObject(clone)
      } else {
        console.log(`3、重新远程加载模型`)
        displayer.loaderRemote.loadFiles(config)
      }
    }

    /**
     * 判断从缓存读出来的JSON是否合法
     * @author zhouwr
     */
    function isJSON(json) {
      if (json.length < 36) {
        return false
      } else {
        return true
      }
    }

    /**
     * 设置灯光
     * @author zhouwr
     */
    function setAmbientLight() {
      if (!displayer.scene.getObjectByName('AmbientLight')) {
        let color = 0x222222
        let light = new THREE.AmbientLight(color)
        light.name = 'AmbientLight'
        displayer.addObject(light)
      }
    }

    function setTitle(title) {
      document.title = title
    }

    let timeout

    function saveState() {
      clearTimeout(timeout)
      timeout = setTimeout(function () {
        displayer.storage.set(displayer.toJSON())
      }, 200)
    }

    let signals = displayer.signals

    signals.objectAllConfiged.add(saveState)

    displayer.signals.deployReload.add(() => {
      displayer.storageRemote.getDeployConfig().then((deployConfig) => {
        deployConfigInit(deployConfig)
      })
    })
  })


  let onWindowResizeTimer
  function onWindowResize() {
    clearTimeout(onWindowResizeTimer)
    onWindowResizeTimer = setTimeout(() => {
      displayer.signals.windowResize.dispatch()
    }, 1000)
  }

  window.addEventListener('resize', onWindowResize, false)
  onWindowResize()

  // ServiceWorker

  if ('serviceWorker' in navigator) {
    try {
      navigator.serviceWorker.register('../js/threejs/libs/sw.js')
    } catch (error) {
    }
  }
</script>

</body>
</html>
